
#ifndef SEMANTICS_EXPRESSION_H

#define SEMANTICS_EXPRESSION_H

#include <stdio.h>
#include "syntax_tree.h"
#include "generic_table.h"

enum SemanticsBuiltInDataType
{
	SemDTInt,
	SemDTFloat,
	SemDTBool,
	SemDTState,
	SemDTTime,
	SemDTVoid,
	SemDTString,
	SemDTEnum,
	SemDTFacility,
	SemDTStorage,
	SemDTQueue,
	SemDTADTable,
	SemDTGroup,
	SemDTOutputStream,
	SemDTTransaction,
	SemDTUserType,
	//SemDTNotBuiltIn
};

class SemanticsDataType
{
public:
	SemanticsDataType()
	{
		builtInType = SemDTVoid;
		DataType = new GenericTable<int>();
	}

	~SemanticsDataType()
	{
		if(DataType != NULL)
		{
			delete DataType;
			DataType = NULL;
		}
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	SemanticsBuiltInDataType builtInType;
	GenericTable<int> * DataType;

};

enum SemanticsOperatorType
{
	OperatorTypeI2f,
	OperatorTypeF2i,
	OperatorTypeIadd,
	OperatorTypeIsub,
	OperatorTypeImul,
	OperatorTypeIdiv,
	OperatorTypeIrem,  // %
	OperatorTypeFadd,
	OperatorTypeFsub,
	OperatorTypeFmul,
	OperatorTypeFdiv,
	OperatorTypeFrem,  // %
	OperatorTypeIcmp_eq,
	OperatorTypeIcmp_ne,
	OperatorTypeIcmp_gt,
	OperatorTypeIcmp_ge,
	OperatorTypeIcmp_lt,
	OperatorTypeIcmp_le,
	OperatorTypeFcmp_eq,
	OperatorTypeFcmp_ne,
	OperatorTypeFcmp_gt,
	OperatorTypeFcmp_ge,
	OperatorTypeFcmp_lt,
	OperatorTypeFcmp_le,
	OperatorTypeIneg,
	OperatorTypeFneg,
	OperatorTypeNot,
	OperatorTypeAnd,
	OperatorTypeOr,
	OperatorTypeXor,
	OperatorTypeBcmp_eq,
	OperatorTypeBcmp_ne
};

class SemanticsExpression; // a trick :)

enum SemanticsOperandSign
{
	SemOpSignPlus,
	SemOpSignMinus
};

class SemanticsVariableValueChunk
{
public:
	SemanticsVariableValueChunk();
	~SemanticsVariableValueChunk();

	GenericTable<int> * Name;
	GenericTable<SemanticsExpression> * Array;
	// ????

};

class SemanticsOperandVariableValue
{
public:
	SemanticsOperandVariableValue();
	~SemanticsOperandVariableValue();

	GenericTable<SemanticsVariableValueChunk> * Chunks;
};

// class for operator NEW ?




enum SemanticsOperandType
{
	SemOpMethodCall, // method call - REQ. CLASS (MAYBE)
	SemOpVariableValue, // <variable_value> - REQ. CLASS
	SemOpExpressionParentheses, // ( <expression> ) - parentheses are not important, because it's on lower level...
	SemOpLiteral, // literal
	SemOpNull, // null
	SemOpNew, // new - REQ. CLASS - operator maybe?????
//	SemOpInstanceOf, // instance of --> not operand, it's operator
//	SemOpCast, // cast operator, not operand, it's operator
};



enum SemanticsOperator
{
	SemOperatorPlus,
	SemOperatorMinus,
	SemOperatorMultiply,
	SemOperatorDivide,
	SemOperatorModulus,
	SemOperatorPower,
	SemOperatorLess,
	SemOperatorLessEqual,
	SemOperatorGreater,
	SemOperatorGreterEqual,
	SemOperatorEqual,
	SemOperatorNotEqual,
	SemOperatorNot,
	SemOperatorOr,
	SemOperatorXor,
	SemOperatorAnd,
	SemOperatorInstanceOf, // LEFT instance of RIGHT
	SemOperatorCast, // (LEFT) RIGHT
	SemOperatorNew // unsure???
};


class SemanticsExpression
{
public:
	SemanticsExpression();
	~SemanticsExpression();

#ifdef DEBUG
	// writes a xml tag like this
	// <expression bla bla bla>
	//   bla bla
	// </expression>
	void DebugXMLOutput(FILE * fo);
	
	/*
	TODO - check this
	{
		DebugXMLOutput("expression", fo);
	}*/
	
	// writes a xml tag like this
	// <expressionName bla bla bla>
	//   bla bla
	// </expressionName>
	void DebugXMLOutput(char * expressionName, FILE * fo);    // mora biti u public dijelu
#endif

	SemanticsOperator Operator;

	SemanticsOperandType LeftOperand;
	SemanticsOperandType RightOperand;

	SemanticsOperandSign LeftOperandSign;
	SemanticsOperandSign RightOperandSign;

	SemanticsExpression * leftExpression;
	SemanticsExpression * rightExpression;

	SemanticsOperandVariableValue * LeftVariableValue;
	SemanticsOperandVariableValue * RightVariableValue;


	// left literal type (enum?) - is it necessary?
	// right literal type (enum?)

	// left literal id (int)
	// right literal id (int)

	// SemanticsMethodStatementMethodCall * MethodCall; -- maybe use this for new operator???
};

#endif

